home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / pcb-1.000 / pcb-1 / pcb-1.3 / menu.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  23KB  |  629 lines

  1. /*
  2.  *                            COPYRIGHT
  3.  *
  4.  *  PCB, interactive printed circuit board design
  5.  *  Copyright (C) 1994,1995 Thomas Nau
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *  Contact addresses for paper mail and Email:
  22.  *  Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
  23.  *  Thomas.Nau@rz.uni-ulm.de
  24.  *
  25.  */
  26.  
  27. static    char    *rcsid = "$Header: /sda4/users/nau/src/pcb/RCS/menu.c,v 2.3 1994/10/29 17:28:29 nau Exp nau $";
  28.  
  29. /* initializes menus and handles callbacks
  30.  */
  31.  
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <sys/types.h>
  35.  
  36. #include "global.h"
  37.  
  38. #include "buffer.h"
  39. #include "data.h"
  40. #include "dialog.h"
  41. #include "draw.h"
  42. #include "mymem.h"
  43. #include "menu.h"
  44. #include "misc.h"
  45. #include "sizedialog.h"
  46.  
  47. #include <X11/Xaw/Form.h>
  48. #include <X11/Xaw/MenuButton.h>
  49. #include <X11/Xaw/SimpleMenu.h>
  50. #include <X11/Xaw/SmeBSB.h>
  51. #include <X11/Xaw/SmeLine.h>
  52.  
  53. /* ---------------------------------------------------------------------------
  54.  * include icon data
  55.  */
  56. #include "check_icon.data"
  57.  
  58. /* ---------------------------------------------------------------------------
  59.  * some local prototypes
  60.  */
  61. static    void    CBPOPUP_Display(Widget, XtPointer, XtPointer);
  62. static    void    CBPOPUP_File(Widget, XtPointer, XtPointer);
  63. static    void    CBPOPUP_Buffer(Widget, XtPointer, XtPointer);
  64. static    void    CB_Action(Widget, XtPointer, XtPointer);
  65. static    void    CB_Position(Widget, XtPointer, XtPointer);
  66. static    void    CB_ElementPosition(Widget, XtPointer, XtPointer);
  67. static    void    CB_TextPosition(Widget, XtPointer, XtPointer);
  68. static    void    CB_ObjectPosition(Widget, XtPointer, XtPointer);
  69. static    void    CB_Sizes(Widget, XtPointer, XtPointer);
  70. static    void    CB_About(Widget, XtPointer, XtPointer);
  71. static    void    RemoveCheckFromMenu(PopupMenuTypePtr);
  72. static    void    CheckEntry(PopupMenuTypePtr, String);
  73. static    void    InitPopupTree(Widget, PopupEntryTypePtr);
  74. static    void    InitPopupMenu(Widget, PopupMenuTypePtr);
  75. static    Widget    InitCommandButton(Widget, CommandButtonTypePtr, Widget, Widget);
  76. static    Boolean    InitCheckPixmap(void);
  77.  
  78. /* ---------------------------------------------------------------------------
  79.  * some local identifiers
  80.  */
  81. static    Pixmap    Check = BadAlloc;
  82.  
  83. /* ---------------------------------------------------------------------------
  84.  * file menu button
  85.  */
  86. static    PopupEntryType    FileMenuEntries[] = {
  87.     { "save", "save layout", CB_Action, "Save,Layout", NULL },
  88.     { "saveas", "save layout as...", CB_Action, "Save,LayoutAs", NULL },
  89.     { "load", "load layout", CB_Action, "Load,Layout", NULL },
  90.     { "loadelement", "load element data to paste-buffer", CB_Action,
  91.         "PasteBuffer,Clear\n"
  92.         "Load,ElemenToBuffer", NULL },
  93.     { "loadlayout", "load layout data to paste-buffer", CB_Action,
  94.         "PasteBuffer,Clear\n"
  95.         "Load,LayoutToBuffer", NULL },
  96.     { "line", NULL, NULL, NULL, NULL },
  97.     { "header", "save connection data of", NULL, NULL, NULL },
  98.     { "savesingle", "a single element", CB_ElementPosition,
  99.         "Save,ElementConnections", NULL },
  100.     { "saveall", "all elements", CB_Action, "Save,AllConnections", NULL },
  101.     { "saveunused", "unused pins", CB_Action, "Save,AllUnusedPins", NULL },
  102.     { "line", NULL, NULL, NULL, NULL },
  103.     { "header", "PostScript output of", NULL, NULL, NULL },
  104.     { "printLayoutPS", "visible layers", CB_Action,
  105.         "Print,Layout,PostScript", NULL },
  106.     { "printPackagePS", "package, pins and vias", CB_Action,
  107.         "Print,Package,PostScript", NULL },
  108.     { "line", NULL, NULL, NULL, NULL },
  109.     { "header", "change name of", NULL, NULL, NULL },
  110.     { "layoutname", "layout", CB_Action, "ChangeName,Layout", NULL },
  111.     { "layername", "active layer", CB_Action, "ChangeName,Layer", NULL },
  112.     { "line", NULL, NULL, NULL, NULL },
  113.     { "new", "start new layout", CB_Action, "New", NULL },
  114.     { "line", NULL, NULL, NULL, NULL },
  115.     { "quit", "quit program", CB_Action, "Quit", NULL },
  116.     { NULL, NULL, NULL, NULL, NULL }};
  117. static    PopupMenuType    FileMenu =
  118.     { "file", NULL, FileMenuEntries, CBPOPUP_File, NULL, NULL};
  119. static    MenuButtonType    FileMenuButton =
  120.     { "file", "File", &FileMenu, NULL};
  121.  
  122. /* ---------------------------------------------------------------------------
  123.  * display menu button
  124.  */
  125. static    PopupEntryType    DisplayMenuEntries[] = {
  126.     { "redraw", "redraw layout", CB_Action, "Display,Redraw", NULL },
  127.     { "center", "center layout", CB_Position, "Display,Center", NULL },
  128.     { "line", NULL, NULL, NULL, NULL },
  129.     { "displayGrid", "display grid", CB_Action, "Display,Grid", NULL },
  130.     { "toggleGrid", "use absolute grid", CB_Position,
  131.         "Display,ToggleGrid", NULL },
  132.     { "toggleAllDirections", "'all-direction' lines", CB_Action,
  133.         "Display,ToggleAllDirections", NULL },
  134.     { "line", NULL, NULL, NULL, NULL },
  135.     { "header", "grid setting", NULL, NULL, NULL },
  136.     { "grid05", " 5 mil", CB_Position, "SetValue,Grid,5", NULL },
  137.     { "grid10", "10 mil", CB_Position, "SetValue,Grid,10", NULL },
  138.     { "grid20", "20 mil", CB_Position, "SetValue,Grid,20", NULL },
  139.     { "grid50", "50 mil", CB_Position, "SetValue,Grid,50", NULL },
  140.     { "grid100", "100 mil", CB_Position, "SetValue,Grid,100", NULL },
  141.     { "gridInc", "increment by 5", CB_Action, "SetValue,Grid,+5", NULL },
  142.     { "gridDec", "decrement by 5", CB_Action, "SetValue,Grid,-5", NULL },
  143.     { "line", NULL, NULL, NULL, NULL },
  144.     { "header", "zoom setting", NULL, NULL, NULL },
  145.     { "zoom1", "1 : 1 ", CB_Position, "SetValue,Zoom,0", NULL },
  146.     { "zoom2", "1 : 2 ", CB_Position, "SetValue,Zoom,1", NULL },
  147.     { "zoom4", "1 : 4 ", CB_Position, "SetValue,Zoom,2", NULL },
  148.     { "zoom8", "1 : 8 ", CB_Position, "SetValue,Zoom,3", NULL },
  149.     { "zoom16", "1 :16 ", CB_Position, "SetValue,Zoom,4", NULL },
  150.     { "line", NULL, NULL, NULL, NULL },
  151.     { "header", "displayed element-name", NULL, NULL, NULL },
  152.     { "canonical", "canonical", CB_Action, "Display,CanonicalName", NULL },
  153.     { "onPCB", "name on PCB", CB_Action, "Display,NameOnPCB", NULL },
  154.     { "line", NULL, NULL, NULL, NULL },
  155.     { NULL, NULL, NULL, NULL, NULL }};
  156. static    PopupMenuType    DisplayMenu =
  157.     { "display", NULL, DisplayMenuEntries, CBPOPUP_Display, NULL, NULL};
  158. static    MenuButtonType    DisplayMenuButton =
  159.     { "display", "Display", &DisplayMenu, NULL};
  160.  
  161. /* ---------------------------------------------------------------------------
  162.  * object menu button
  163.  */
  164. static    PopupEntryType    ObjectMenuEntries[] = {
  165.     { "header", "elements", NULL, NULL, NULL },
  166.     { "pinout", "display pinout", CB_ElementPosition, "Display,Pinout", NULL },
  167.     { "changeName", "change name", CB_ElementPosition,
  168.         "ChangeName,Object", NULL },
  169.     { "line", NULL, NULL, NULL, NULL },
  170.     { "header", "text objects", NULL, NULL, NULL },
  171.     { "edit", "edit", CB_TextPosition, "ChangeName,Object", NULL },
  172.     { NULL, NULL, NULL, NULL, NULL }};
  173. static    PopupMenuType    ObjectMenu =
  174.     { "objects",  NULL, ObjectMenuEntries, NULL, NULL, NULL };
  175. static    MenuButtonType    ObjectMenuButton =
  176.     { "objects", "Objects", &ObjectMenu, NULL};
  177.  
  178. /* ---------------------------------------------------------------------------
  179.  * selection menu button
  180.  */
  181. static    PopupEntryType    SelectionMenuEntries[] = {
  182.     { "select", "select all objects", CB_Action, "Select,All", NULL },
  183.     { "selectconnection", "select all connected objects", CB_Action,
  184.         "Select,Connection", NULL },
  185.     { "line", NULL, NULL, NULL, NULL },
  186.     { "unselect", "unselect all objects", CB_Action, "Unselect,All", NULL },
  187.     { "unselectconnection", "unselect all connected objects", CB_Action,
  188.         "Unselect,Connection", NULL },
  189.     { "line", NULL, NULL, NULL, NULL },
  190.     { "remove", "remove selected objects", CB_Action,
  191.         "RemoveSelected", NULL },
  192.     { "line", NULL, NULL, NULL, NULL },
  193.     { "header", "change size of selected objects", NULL, NULL, NULL },
  194.     { "decrementline", "lines -10 mil", CB_Action,
  195.         "ChangeSize,SelectedLines,-10", NULL },
  196.     { "incrementline", "lines +10 mil", CB_Action,
  197.         "ChangeSize,SelectedLines,+10", NULL },
  198.     { "decrementvia", "vias -10 mil", CB_Action,
  199.         "ChangeSize,SelectedVias,-10", NULL },
  200.     { "incrementvia", "vias +10 mil", CB_Action,
  201.         "ChangeSize,SelectedVias,+10", NULL },
  202.     { "decrementpin", "pins -10 mil", CB_Action,
  203.         "ChangeSize,SelectedPins,-10", NULL },
  204.     { "incrementpin", "pins +10 mil", CB_Action,
  205.         "ChangeSize,SelectedPins,+10", NULL },
  206.     { "line", NULL, NULL, NULL, NULL },
  207.     { "header", "change drilling hole of selected objects", NULL, NULL, NULL },
  208.     { "decrementviahole", "vias -10 mil", CB_Action,
  209.         "Change2ndSize,SelectedVias,-10", NULL },
  210.     { "incrementviahole", "vias +10 mil", CB_Action,
  211.         "Change2ndSize,SelectedVias,+10", NULL },
  212.     { "decrementpinhole", "pins -10 mil", CB_Action,
  213.         "Change2ndSize,SelectedPins,-10", NULL },
  214.     { "incrementpinhole", "pins +10 mil", CB_Action,
  215.         "Change2ndSize,SelectedPins,+10", NULL },
  216.     { NULL, NULL, NULL, NULL, NULL }};
  217. static    PopupMenuType    SelectionMenu =
  218.     { "selection",  NULL, SelectionMenuEntries, NULL, NULL, NULL };
  219. static    MenuButtonType    SelectionMenuButton =
  220.     { "selection", "Selection", &SelectionMenu, NULL};
  221.  
  222. /* ---------------------------------------------------------------------------
  223.  * paste buffer menu button
  224.  */
  225. static    PopupEntryType    BufferMenuEntries[] = {
  226.     { "copy", "copy selection to buffer", CB_Action,
  227.         "PasteBuffer,Clear\n"
  228.         "PasteBuffer,AddSelected\n",
  229.         NULL },
  230.     { "cut", "copy selection to buffer and cut", CB_Action,
  231.         "PasteBuffer,Clear\n"
  232.         "PasteBuffer,AddSelected\n"
  233.         "RemoveSelected\n",
  234.         NULL },
  235.     { "paste", "paste buffer to layout", CB_Action, "Mode,PasteBuffer", NULL },
  236.     { "line", NULL, NULL, NULL, NULL },
  237.     { "rotate", "rotate buffer 90 deg", CB_Action,
  238.         "Mode,PasteBuffer\n"
  239.         "PasteBuffer,Rotate,1",
  240.         NULL },
  241.     { "line", NULL, NULL, NULL, NULL },
  242.     { "clear", "clear buffer", CB_Action, "PasteBuffer,Clear", NULL },
  243.     { "line", NULL, NULL, NULL, NULL },
  244.     { "header", "select current buffer", NULL, NULL, NULL },
  245.     { "buffer1", "#1", CB_Action, "PasteBuffer,1", NULL },
  246.     { "buffer2", "#2", CB_Action, "PasteBuffer,2", NULL },
  247.     { "buffer3", "#3", CB_Action, "PasteBuffer,3", NULL },
  248.     { "buffer4", "#4", CB_Action, "PasteBuffer,4", NULL },
  249.     { "buffer5", "#5", CB_Action, "PasteBuffer,5", NULL },
  250.     { NULL, NULL, NULL, NULL, NULL }};
  251. static    PopupMenuType    BufferMenu =
  252.     { "buffer",  NULL, BufferMenuEntries, CBPOPUP_Buffer, NULL, NULL };
  253. static    MenuButtonType    BufferMenuButton =
  254.     { "buffer", "Buffer", &BufferMenu, NULL};
  255.  
  256. /* ---------------------------------------------------------------------------
  257.  * connection menu button
  258.  */
  259. static    PopupEntryType    ConnectionMenuEntries[] = {
  260.     { "lookup", "lookup connection to object", CB_ObjectPosition,
  261.         "Connection,Find", NULL },
  262.     { "resetPV", "reset scanned pins/vias", CB_Action,
  263.         "Connection,ResetPinsAndVias\n"
  264.         "Display,Redraw", NULL },
  265.     { "resetLR", "reset scanned lines/polygons", CB_Action,
  266.         "Connection,ResetLinesAndPolygons\n"
  267.         "Display,Redraw", NULL },
  268.     { "reset", "reset all connections", CB_Action,
  269.         "Connection,Reset\n"
  270.         "Display,Redraw", NULL },
  271.     { NULL, NULL, NULL, NULL, NULL }};
  272. static    PopupMenuType    ConnectionMenu =
  273.     { "connections",  NULL, ConnectionMenuEntries, NULL, NULL, NULL };
  274. static    MenuButtonType    ConnectionMenuButton =
  275.     { "connections", "Connections", &ConnectionMenu, NULL};
  276.  
  277. /* ---------------------------------------------------------------------------
  278.  * undo menu button
  279.  */
  280. static    PopupEntryType    UndoMenuEntries[] = {
  281.     { "undo", "undo last destructive operation", CB_Action, "Undo", NULL },
  282.     { "clear", "clear undo-buffer", CB_Action, "Undo,ClearList", NULL },
  283.     { NULL, NULL, NULL, NULL, NULL }};
  284. static    PopupMenuType    UndoMenu =
  285.     { "undo",  NULL, UndoMenuEntries, NULL, NULL, NULL };
  286. static    MenuButtonType    UndoMenuButton =
  287.     { "undo", "Undo", &UndoMenu, NULL};
  288.  
  289. /* ----------------------------------------------------------------------
  290.  * command buttons
  291.  */
  292. static    CommandButtonType    AboutButton =
  293.     { "about", "About", CB_About, NULL, NULL },
  294.                             SizesButton =
  295.     { "sizes", "Sizes", CB_Sizes, NULL, NULL };
  296.  
  297.  
  298.  
  299. /* ----------------------------------------------------------------------
  300.  * menu callback interface for actions routines that don't need
  301.  * position information
  302.  *
  303.  * ClientData passes a pointer to a comma seperated list of arguments.
  304.  * The first one determines the action routine to be called, the
  305.  * rest of them are arguments to the action routine
  306.  *
  307.  * if more than one action is to be called a new list is seperated
  308.  * by '\n'
  309.  */
  310. static void CB_Action(Widget W, XtPointer ClientData, XtPointer CallData)
  311. {
  312.     static    char    **array = NULL;
  313.     static    size_t    number = 0;
  314.             int        n;
  315.             char    *copy,
  316.                     *current,
  317.                     *next,
  318.                     *token;
  319.  
  320.         /* get a copy of the string and split it */
  321.     copy = MyStrdup((char *) ClientData, "CB_CallActionWithoutPosition()");
  322.  
  323.         /* first loop over all action routines;
  324.          * strtok cannot be used in nested loops because it saves
  325.          * a pointer in a private data area which would be corrupted
  326.          * by th inner loop
  327.          */
  328.     for (current = copy; current; current = next)
  329.     {
  330.             /* lookup seperating '\n' character;
  331.              * update pointer if not at the end of the string
  332.              */
  333.         for (next = current; *next && *next != '\n'; next++);
  334.         if (*next)
  335.         {
  336.             *next = '\0';
  337.             next++;
  338.         }
  339.         else
  340.             next = NULL;
  341.         
  342.         token = strtok(current, ",");
  343.         for (n = 0; token; token = strtok(NULL, ","), n++)
  344.         {
  345.                 /* allocate memory if necessary */
  346.             if (n >= number)
  347.             {
  348.                 number += 10;
  349.                 array = MyRealloc(array, number*sizeof(char *),
  350.                     "CB_CallActionWithoutPosition()");
  351.             }
  352.             array[n] = token;
  353.         }
  354.             /* call action routine */
  355.         XtCallActionProc(Output.Output, array[0], NULL, &array[1], n-1);
  356.     }
  357.  
  358.         /* release memory */
  359.     SaveFree(copy);
  360. }
  361.  
  362. /* ----------------------------------------------------------------------
  363.  * menu callback interface for misc actions routines that need
  364.  * position information
  365.  */
  366. static void CB_Position(Widget W, XtPointer ClientData, XtPointer CallData)
  367. {
  368.     if (GetPosition("move pointer to the appropriate screen position and press a button"))
  369.         CB_Action(W, ClientData, CallData);
  370. }
  371.  
  372. /* ----------------------------------------------------------------------
  373.  * menu callback interface for element related actions routines that need
  374.  * position information
  375.  */
  376. static void CB_ElementPosition(Widget W,
  377.     XtPointer ClientData, XtPointer CallData)
  378. {
  379.     if (GetPosition("press a button at the elements location"))
  380.         CB_Action(W, ClientData, CallData);
  381. }
  382.  
  383. /* ----------------------------------------------------------------------
  384.  * menu callback interface for text related actions routines that need
  385.  * position information
  386.  */
  387. static void CB_TextPosition(Widget W,
  388.     XtPointer ClientData, XtPointer CallData)
  389. {
  390.     if (GetPosition("press a button at the text location"))
  391.         CB_Action(W, ClientData, CallData);
  392. }
  393.  
  394. /* ----------------------------------------------------------------------
  395.  * menu callback interface for pin/via related actions routines that need
  396.  * position information update
  397.  */
  398. static void CB_ObjectPosition(Widget W,
  399.     XtPointer ClientData, XtPointer CallData)
  400. {
  401.     if (GetPosition("press a button at an 'connecting-objects' location"))
  402.         CB_Action(W, ClientData, CallData);
  403. }
  404.  
  405. /* ---------------------------------------------------------------------- 
  406.  * called before display menu is popped up
  407.  * used to mark the current grid-mode, zoom value ...
  408.  */
  409. static void CBPOPUP_Display(Widget W, XtPointer ClientData, XtPointer CallData)
  410. {
  411.     RemoveCheckFromMenu(&DisplayMenu);
  412.     XtSetSensitive(XtNameToWidget(DisplayMenu.W, "displayGrid"),
  413.         (TO_SCREEN(PCB->Grid) >= MIN_GRID_DISTANCE));
  414.     if (TEST_FLAG(ABSOLUTEFLAG, PCB))
  415.         CheckEntry(&DisplayMenu, "toggleGrid");
  416.     if (TEST_FLAG(ALLDIRCETIONFLAG, PCB))
  417.         CheckEntry(&DisplayMenu, "toggleAllDirections");
  418.     if (Settings.DrawGrid)
  419.         CheckEntry(&DisplayMenu, "displayGrid");
  420.     switch(PCB->Zoom)
  421.     {
  422.         case 0:    CheckEntry(&DisplayMenu, "zoom1"); break;
  423.         case 1:    CheckEntry(&DisplayMenu, "zoom2"); break;
  424.         case 2:    CheckEntry(&DisplayMenu, "zoom4"); break;
  425.         case 3:    CheckEntry(&DisplayMenu, "zoom8"); break;
  426.         case 4:    CheckEntry(&DisplayMenu, "zoom16"); break;
  427.     }
  428.     CheckEntry(&DisplayMenu,
  429.         TEST_FLAG(CANONICALFLAG, PCB) ? "canonical" : "onPCB");
  430. }
  431.  
  432. /* ---------------------------------------------------------------------- 
  433.  * called before file menu is popped up
  434.  * enables/disables printing
  435.  */
  436. static void CBPOPUP_File(Widget W, XtPointer ClientData, XtPointer CallData)
  437. {
  438.     XtSetSensitive(XtNameToWidget(FileMenu.W, "printLayoutPS"),
  439.         !IsDataEmpty(PCB->Data));
  440. }
  441.  
  442. /* ---------------------------------------------------------------------- 
  443.  * called before buffer menu is popped up
  444.  */
  445. static void CBPOPUP_Buffer(Widget W, XtPointer ClientData, XtPointer CallData)
  446. {
  447.     RemoveCheckFromMenu(&BufferMenu);
  448.     switch(Settings.BufferNumber)
  449.     {
  450.         case 0:    CheckEntry(&BufferMenu, "buffer1"); break;
  451.         case 1:    CheckEntry(&BufferMenu, "buffer2"); break;
  452.         case 2:    CheckEntry(&BufferMenu, "buffer3"); break;
  453.         case 3:    CheckEntry(&BufferMenu, "buffer4"); break;
  454.         case 4:    CheckEntry(&BufferMenu, "buffer5"); break;
  455.     }
  456. }
  457.  
  458. /* ---------------------------------------------------------------------- 
  459.  * callback routine used by sizes button
  460.  */
  461. static void CB_Sizes(Widget W, XtPointer ClientData, XtPointer CallData)
  462. {
  463.     SizeDialog();
  464. }
  465.  
  466. /* ---------------------------------------------------------------------- 
  467.  * callback routine used by about button
  468.  */
  469. static void CB_About(Widget W, XtPointer ClientData, XtPointer CallData)
  470. {
  471.     AboutDialog();
  472. }
  473.  
  474. /* ---------------------------------------------------------------------------
  475.  * remove all 'check' symbols from menu entries
  476.  */
  477. static void RemoveCheckFromMenu(PopupMenuTypePtr MenuPtr)
  478. {
  479.     PopupEntryTypePtr    entries = MenuPtr->Entries;
  480.  
  481.     for (; entries->Name; entries++)
  482.         if (entries->Label)
  483.             XtVaSetValues(entries->W, XtNleftBitmap, None, NULL);
  484. }
  485.  
  486. /* ---------------------------------------------------------------------------
  487.  * add 'check' symbol to menu entry
  488.  */
  489. static void CheckEntry(PopupMenuTypePtr MenuPtr, String WidgetName)
  490. {
  491.     PopupEntryTypePtr    entries = MenuPtr->Entries;
  492.  
  493.     if (InitCheckPixmap())
  494.         for (; entries->Name; entries++)
  495.             if (entries->Label && !strcmp(entries->Name, (char *) WidgetName))
  496.             {
  497.                 XtVaSetValues(entries->W, XtNleftBitmap, Check, NULL);
  498.                 return;
  499.             }
  500. }
  501.  
  502. /* ---------------------------------------------------------------------------
  503.  * initializes a command button
  504.  */
  505. static Widget InitCommandButton(Widget Parent, CommandButtonTypePtr CommandButtonPtr, Widget Top, Widget Left)
  506. {
  507.     CommandButtonPtr->W = XtVaCreateManagedWidget(CommandButtonPtr->Name, commandWidgetClass,
  508.         Parent,
  509.         XtNlabel, CommandButtonPtr->Label,
  510.         XtNfromHoriz, Left,
  511.         XtNfromVert, Top,
  512.         LAYOUT_TOP,
  513.         NULL);
  514.     XtAddCallback(CommandButtonPtr->W, XtNcallback,
  515.         CommandButtonPtr->Callback, CommandButtonPtr->ClientData);
  516.  
  517.         /* return the created button widget to position some others */
  518.     return(CommandButtonPtr->W);
  519. }
  520.  
  521. /* ---------------------------------------------------------------------------
  522.  * initializes a menu tree
  523.  * depending on the 'Name' field of the struct either a smeBSB or a
  524.  * smeLine widget is created. If a callback routine is defined for the
  525.  * smeBSB widget it will be registered else the entry will be disabled
  526.  */
  527. static void InitPopupTree(Widget Parent, PopupEntryTypePtr EntryPtr)
  528. {
  529.     for (; EntryPtr->Name; EntryPtr++)
  530.     {
  531.             /* check if it's only a seperator */
  532.         if (EntryPtr->Label)
  533.         {
  534.             EntryPtr->W = XtVaCreateManagedWidget(EntryPtr->Name, smeBSBObjectClass,
  535.                 Parent,
  536.                 XtNlabel, EntryPtr->Label,
  537.                 XtNleftMargin, 12, 
  538.                 XtNsensitive, True,
  539.                 NULL);
  540.             if (EntryPtr->Callback)
  541.                 XtAddCallback(EntryPtr->W, XtNcallback,
  542.                     EntryPtr->Callback, (XtPointer) EntryPtr->ClientData);
  543.             else
  544.                     /* entry is not selectable */
  545.                 XtVaSetValues(EntryPtr->W,
  546.                     XtNsensitive, False,
  547.                     XtNvertSpace, 60,
  548.                     NULL);
  549.         }
  550.         else
  551.             XtVaCreateManagedWidget("menuLine",smeLineObjectClass,Parent,NULL);
  552.     }
  553. }
  554.  
  555. /* ---------------------------------------------------------------------------
  556.  * initializes one popup menu
  557.  * create a popup shell, add all entries to it and register the popup and
  558.  * popdown callback functions if required
  559.  */
  560. static void InitPopupMenu(Widget Parent, PopupMenuTypePtr MenuPtr)
  561. {
  562.     MenuPtr->W = XtVaCreatePopupShell(MenuPtr->Name, simpleMenuWidgetClass,
  563.         Parent,
  564.         XtNlabel, MenuPtr->Label,
  565.         XtNsensitive, True,
  566.         NULL);
  567.     InitPopupTree(MenuPtr->W, MenuPtr->Entries);
  568.  
  569.         /* install popup and popdown callbacks */
  570.     if (MenuPtr->CB_Popup)
  571.         XtAddCallback(MenuPtr->W, XtNpopupCallback, MenuPtr->CB_Popup, NULL);
  572.     if (MenuPtr->CB_Popdown)
  573.         XtAddCallback(MenuPtr->W, XtNpopupCallback, MenuPtr->CB_Popdown, NULL);
  574. }
  575.  
  576. /* ---------------------------------------------------------------------------
  577.  * initializes one menubutton plus it's menu
  578.  * create a menu button widget first than add the popup shell to it
  579.  */
  580. Widget InitMenuButton(Widget Parent,
  581.     MenuButtonTypePtr MenuButtonPtr, Widget Top, Widget Left)
  582. {
  583.     MenuButtonPtr->W = XtVaCreateManagedWidget(MenuButtonPtr->Name, menuButtonWidgetClass,
  584.         Parent,
  585.         XtNlabel, MenuButtonPtr->Label,
  586.         XtNmenuName, MenuButtonPtr->PopupMenu->Name,
  587.         XtNfromHoriz, Left,
  588.         XtNfromVert, Top,
  589.         LAYOUT_TOP,
  590.         NULL);
  591.     InitPopupMenu(MenuButtonPtr->W, MenuButtonPtr->PopupMenu);
  592.  
  593.         /* return the created button widget to position some others */
  594.     return(MenuButtonPtr->W);
  595. }
  596.  
  597. /* ---------------------------------------------------------------------------
  598.  * initializes 'check' pixmap if not already done
  599.  */
  600. static Boolean InitCheckPixmap(void)
  601. {
  602.     if (Check == BadAlloc)
  603.         Check = XCreateBitmapFromData(Dpy,
  604.                     RootWindowOfScreen(XtScreen(Output.Toplevel)),
  605.                     check_icon_bits, check_icon_width, check_icon_height);
  606.     return(Check != BadAlloc ? True : False);
  607. }
  608.  
  609. /* ---------------------------------------------------------------------------
  610.  * initializes button related menus
  611.  * also initializes control panel
  612.  */
  613. void InitMenu(Widget Parent, Widget Top, Widget Left)
  614. {
  615.     Widget    last;
  616.  
  617.     last = InitCommandButton(Parent, &AboutButton, Top, Left);
  618.     last = InitMenuButton(Parent, &FileMenuButton, Top, last);
  619.     last = InitMenuButton(Parent, &DisplayMenuButton, Top, last);
  620.     last = InitCommandButton(Parent, &SizesButton, Top, last);
  621.     last = InitMenuButton(Parent, &ObjectMenuButton, Top, last);
  622.     last = InitMenuButton(Parent, &SelectionMenuButton, Top, last);
  623.     last = InitMenuButton(Parent, &BufferMenuButton, Top, last);
  624.     last = InitMenuButton(Parent, &ConnectionMenuButton, Top, last);
  625.     last = InitMenuButton(Parent, &UndoMenuButton, Top, last);
  626.     Output.Menu = last;
  627. }
  628.  
  629.